﻿using System.Collections.ObjectModel;
using System.Linq;
using CuteRibs.D3Armory.Models;
using CuteRibs.D3Armory.Resources;
using CuteRibs.MVVMLib;

namespace CuteRibs.D3Armory.ViewModels
{
	public class ProfileViewModel : ViewModelBase
	{
		private Realm realm;
		private BattleTag battleTag;
		private string number;
		private string lastUpdated;
		private string blacksmith;
		private string jeweler;
		private string hardcoreBlacksmith;
		private string hardcoreJeweler;

		public Realm Realm
		{
			get { return this.realm; }
			set
			{
				if (this.realm != value)
				{
					this.realm = value;
					this.NotifyPropertyChanged("Realm");
				}
			}
		}

		public BattleTag BattleTag
		{
			get { return this.battleTag; }
			set
			{
				if (this.battleTag != value)
				{
					this.battleTag = value;
					this.NotifyPropertyChanged("BattleTag");
				}
			}
		}

		public string Number
		{
			get { return this.number; }
			set
			{
				if (this.number != value)
				{
					this.number = value;
					this.NotifyPropertyChanged("Number");
				}
			}
		}

		public string LastUpdated
		{
			get { return this.lastUpdated; }
			set
			{
				if (this.lastUpdated != value)
				{
					this.lastUpdated = value;
					this.NotifyPropertyChanged("LastUpdated");
				}
			}
		}

		public string Blacksmith
		{
			get { return this.blacksmith; }
			set
			{
				if (this.blacksmith != value)
				{
					this.blacksmith = value;
					this.NotifyPropertyChanged("Blacksmith");
				}
			}
		}

		public string Jeweler
		{
			get { return this.jeweler; }
			set
			{
				if (this.jeweler != value)
				{
					this.jeweler = value;
					this.NotifyPropertyChanged("Jeweler");
				}
			}
		}

		public string HardcoreBlacksmith
		{
			get { return this.hardcoreBlacksmith; }
			set
			{
				if (this.hardcoreBlacksmith != value)
				{
					this.hardcoreBlacksmith = value;
					this.NotifyPropertyChanged("HardcoreBlacksmith");
				}
			}
		}

		public string HardcoreJeweler
		{
			get { return this.hardcoreJeweler; }
			set
			{
				if (this.hardcoreJeweler != value)
				{
					this.hardcoreJeweler = value;
					this.NotifyPropertyChanged("HardcoreJeweler");
				}
			}
		}

		public Profile Profile { get; set; }

		public string[] TimePlayedPercentages { get; set; }
		public double[] TimePlayedWidths { get; set; }

		public string NormalProgression { get; set; }
		public string HardcoreProgression { get; set; }

		public ObservableCollection<NormalHeroViewModel> NormalHeroes { get; set; }
		public ObservableCollection<LargeHeroViewModel> LargeHeroes { get; set; }

		public ProfileViewModel(Profile profile = null)
		{
			this.Profile = profile;

			if (this.Profile != null)
			{
				this.BattleTag = this.Profile.BattleTag;
				this.Number = "#" + this.BattleTag.Number.ToString();
				this.LastUpdated = string.Format("{0}: {1}", AppRes.LastUpdated, this.Profile.LastUpdated);
				this.NormalHeroes = new ObservableCollection<NormalHeroViewModel>(profile.Heroes.Select(h => new NormalHeroViewModel(h)));
				this.LargeHeroes = new ObservableCollection<LargeHeroViewModel>(profile.Heroes.Select(h => new LargeHeroViewModel(h)));
				this.SetTimePlayed(this.Profile.TimePlayed);
				this.SetArtisans(this.Profile.Artisans, this.Profile.HardcoreArtisans);
				this.NormalProgression = GetHighestProgression(this.Profile.Progression);
				this.HardcoreProgression = GetHighestProgression(this.Profile.HardcoreProgression);
			}
		}

		private void SetTimePlayed(GameTimePlayed timePlayed)
		{
			var values = new double[] { timePlayed.Barbarian, timePlayed.DemonHunter, timePlayed.Monk, timePlayed.WitchDoctor, timePlayed.Wizard };
			var total = values.Aggregate((s, f) => s + f);
			this.TimePlayedPercentages = values.Select(v => (v / total).ToString("P0")).ToArray();
			this.TimePlayedWidths = values.Select(v => v / total * 300).ToArray();
		}

		private void SetArtisans(Artisan[] artisan, Artisan[] hardcoreArtisan)
		{
			this.Blacksmith = string.Format(AppRes.ArtisanLevel, artisan[0].Level, AppRes.Normal);
			this.Jeweler = string.Format(AppRes.ArtisanLevel, artisan[1].Level, AppRes.Hardcore);
			this.HardcoreBlacksmith = string.Format(AppRes.ArtisanLevel, hardcoreArtisan[0].Level, AppRes.Normal);
			this.HardcoreJeweler = string.Format(AppRes.ArtisanLevel, hardcoreArtisan[1].Level, AppRes.Hardcore);
		}

		private static string GetHighestProgression(GameProgression gameProgression)
		{
			string progression;

			var actProgressions = new ActProgression[] 
			{
				gameProgression.Normal.Act1,
				gameProgression.Normal.Act2,
				gameProgression.Normal.Act3,
				gameProgression.Normal.Act4,
				gameProgression.Nightmare.Act1,
				gameProgression.Nightmare.Act2,
				gameProgression.Nightmare.Act3,
				gameProgression.Nightmare.Act4,
				gameProgression.Hell.Act1,
				gameProgression.Hell.Act2,
				gameProgression.Hell.Act3,
				gameProgression.Hell.Act4,
				gameProgression.Inferno.Act1,
				gameProgression.Inferno.Act2,
				gameProgression.Inferno.Act3,
				gameProgression.Inferno.Act4
			};

			int index = -1;

			for (int i = actProgressions.Length - 1; i > -1; i--)
			{
				if (actProgressions[i].Completed)
				{
					index = i;
					break;
				}
			}

			if (index > -1)
			{
				if (index < 4)
				{
					progression = AppRes.Normal;
				}
				else if (index < 8)
				{
					progression = AppRes.Nightmare;
				}
				else if (index < 12)
				{
					progression = AppRes.Hell;
				}
				else
				{
					progression = AppRes.Inferno;
				}

				var act = string.Empty;

				switch (index % 4)
				{
					case 0:
						act = AppRes.Act1;
						break;
					case 1:
						act = AppRes.Act2;
						break;
					case 2:
						act = AppRes.Act3;
						break;
					case 3:
						act = AppRes.Act4;
						break;
				}

				progression += " " + act;
			}
			else
			{
				progression = AppRes.NoProgression;
			}

			return progression;
		}
	}
}
